/*
 * sensors.c
 *
 *  Created on: 25 apr. 2013
 *      Author: Pascal
 */

#include "sensors.h"

/**
 * Fills a character array (at least 21 long) with a timestamp
 *
 * Not finished...
 */
void getTimeStamp(char string[]) {
	int stringIndex = 0;

	time_t t = time(0);   // get time now
	struct tm * now = localtime(&t);

	stringIndex += sprintf(&string[stringIndex], "%d/", 1900 + now->tm_year);
	stringIndex += sprintf(&string[stringIndex], "%d/", now->tm_mon);
	stringIndex += sprintf(&string[stringIndex], "%d/", now->tm_mday);
	stringIndex += sprintf(&string[stringIndex], "%d/", now->tm_hour);
	stringIndex += sprintf(&string[stringIndex], "%d/", now->tm_min);
	stringIndex += sprintf(&string[stringIndex], "%d/", now->tm_sec);
	// Not an entirely correct way to get the current milliseconds,
	// but it will do for now.
	stringIndex += sprintf(&string[stringIndex], "%d", clock() / (CLOCKS_PER_SEC / 1000));
}

/**
 * Inits an analog sensor with some randomly determined properties.
 */
void initAnalogSensor(struct AnalogSensor *sensor, int number) {
	//	strcpy(sensor->unit, &ANALOG_SENSOR_DEFAULT_UNIT);

	double upperLimit = randBetween(SENSOR_MAX_UPPER_LIMIT, SENSOR_MIN_UPPER_LIMIT);
	double lowerLimit = upperLimit - randBetween(SENSOR_MAX_LOWER_LIMIT_DEVIATION, SENSOR_MIN_LOWER_LIMIT_DEVIATION);
	sensor->lowerLimit = lowerLimit;
	sensor->upperLimit = upperLimit;
	sensor->value = generateAnalogValue(sensor);
	getRandomUnit(sensor);

	// Old init
//	sensor->lowerLimit = ANALOG_SENSOR_DEFAULT_LOWER_LIMIT;
//	sensor->upperLimit = ANALOG_SENSOR_DEFAULT_UPPER_LIMIT;
//	sensor->value = ANALOG_SENSOR_DEFAULT_VALUE;
	sprintf(sensor->name, "AnalogSensor%d", number);
	strcpy(sensor->lowerLimitAlarmName, &ANALOG_SENSOR_DEFAULT_LOWER_ALARM_NAME);
	strcpy(sensor->upperLimitAlarmName, &ANALOG_SENSOR_DEFAULT_UPPER_ALARM_NAME);
	strcpy(sensor->timeStamp, &SENSOR_DEFAULT_TIMESTAMP);
}

void initBinarySensor(struct BinarySensor *sensor, int number) {
	sensor->value = 0;
	sprintf(sensor->name, "BinarySensor%d", number);
	strcpy(sensor->timeStamp, &SENSOR_DEFAULT_TIMESTAMP);
	strcpy(sensor->alarmName, &BINARY_SENSOR_DEFAULT_ALARM_NAME);
}

void initSensors() {
	int i;
	// Seed random number generator
	srandom(time(NULL));

	// Init sensors
	for (i = 0; i < ANALOG_SENSORS_10MS_AMOUNT; i++) {
		initAnalogSensor(&analogSensors10ms[i], i+1);
	}
	for (i = 0; i < ANALOG_SENSORS_100MS_AMOUNT; i++) {
		initAnalogSensor(&analogSensors100ms[i], i+1);
	}
	for (i = 0; i < BINARY_SENSORS_AMOUNT; i++) {
		initBinarySensor(&binarySensors[i], i + 1);
	}
}

/**
 * Reads(= generates) the 10ms analog sensors.
 */
void read10msSensorValues() {
	int i;
	char timeStamp[21];
	getTimeStamp(timeStamp);
	for (i = 0; i < ANALOG_SENSORS_10MS_AMOUNT; i++) {
		analogSensors10ms[i].value = generateAnalogValue(&analogSensors10ms[i]);
		strcpy(analogSensors10ms[i].timeStamp, timeStamp);
	}
}

/**
 * Reads(= generates) values for the 100ms analog sensors and the binary sensors.
 */
void read100msSensorValues() {
	int i;
	char timeStamp[21];
	getTimeStamp(timeStamp);
	for (i = 0; i < ANALOG_SENSORS_100MS_AMOUNT; i++) {
		analogSensors100ms[i].value = generateAnalogValue(&analogSensors100ms[i]);
		strcpy(analogSensors100ms[i].timeStamp, timeStamp);
	}
	for (i = 0; i < BINARY_SENSORS_AMOUNT; i++) {
		binarySensors[i].value = generateBinaryValue();
		strcpy(binarySensors[i].timeStamp, timeStamp);
	}
}

/**
 * Checks if any 10ms sensors have exceeded alarm limits
 */
void check10msSensorsForAlarms() {
	char alarmJsonBuffer[200];
	int i, size, exceeds;
	for (i = 0; i < ANALOG_SENSORS_10MS_AMOUNT; i++) {
		exceeds = analogSensorExceedsLimits(&analogSensors10ms[i]);
		if (exceeds == 0) {
			// Sensor value is fine
			continue;
		} else if (exceeds < 0) {
			// Lower limit exceeded
			size = createAlarmJson(analogSensors10ms[i].name,
					analogSensors10ms[i].lowerLimitAlarmName, alarmJsonBuffer);
			putInSendBuffers(alarmJsonBuffer, size);
		} else {
			// Upper limit exceeded
			size = createAlarmJson(analogSensors10ms[i].name,
					analogSensors10ms[i].upperLimitAlarmName, alarmJsonBuffer);
			putInSendBuffers(alarmJsonBuffer, size);
		}
	}
}

/**
 * Checks if any 100ms sensors have exceeded alarm limits
 */
void check100msSensorsForAlarms() {
	char alarmJsonBuffer[200];
	int i, size, exceeds;
	for (i = 0; i < ANALOG_SENSORS_100MS_AMOUNT; i++) {
		exceeds = analogSensorExceedsLimits(&analogSensors100ms[i]);
		if (exceeds == 0) {
			// Sensor value is fine
			continue;
		} else if (exceeds < 0) {
			// Lower limit exceeded
			size = createAlarmJson(analogSensors100ms[i].name,
					analogSensors100ms[i].lowerLimitAlarmName, alarmJsonBuffer);
			putInSendBuffers(alarmJsonBuffer, size);
		} else {
			// Upper limit exceeded
			size = createAlarmJson(analogSensors100ms[i].name,
					analogSensors100ms[i].upperLimitAlarmName, alarmJsonBuffer);
			putInSendBuffers(alarmJsonBuffer, size);
		}
	}
	for (i = 0; i < BINARY_SENSORS_AMOUNT; i++) {
		if (binarySensorExceedsLimits(&binarySensors[i])) {
			size = createAlarmJson(binarySensors[i].name, binarySensors[i].alarmName, alarmJsonBuffer);
			putInSendBuffers(alarmJsonBuffer, size);
		}
	}
}

/**
 * Returns 1 if the sensor exceeds its upperlimit, -1 if exceeds lowerlimit, else 0;
 */
int analogSensorExceedsLimits(struct AnalogSensor *sensor) {
	if (sensor->value > sensor->upperLimit) {
		return 1;
	} else if (sensor->value < sensor->lowerLimit) {
		return -1;
	} else {
		return 0;
	}
}

/**
 * Returns 1 if the sensor exceeds its limits, else returns 0;
 */
int binarySensorExceedsLimits(struct BinarySensor *sensor) {
	if (strcmp(sensor->alarmName, "no alarm") == 0) {
		return 0;
	} else {
		return sensor->value;
	}
}

void printSensors() {
	int i;
	for (i = 0; i < ANALOG_SENSORS_10MS_AMOUNT; i++) {
		printf("Analog 10ms #%d: %f\n", i + 1, analogSensors10ms[i].value);
	}
	for (i = 0; i < ANALOG_SENSORS_100MS_AMOUNT; i++) {
		printf("Analog 100ms #%d: %f\n", i + 1, analogSensors100ms[i].value);
	}
	for (i = 0; i < BINARY_SENSORS_AMOUNT; i++) {
		printf("Binary #%d: %d\n", i + 1, binarySensors[i].value);
	}
}

/**
 * Change an analog sensor's alarm values using an AnalogAlarmChangeStruct
 */
void changeAnalogSensorAlarmValues(struct AnalogAlarmChangeStruct *changeStruct, struct AnalogSensor *sensor) {
	sensor->lowerLimit = changeStruct->lowerLimit;
	sensor->upperLimit = changeStruct->upperLimit;
	printf("Changed analog sensor %s", sensor->name);
}

void findAndChangeAnalogAlarm(struct AnalogAlarmChangeStruct* changeStruct) {
	int i;
	for (i = 0; i < ANALOG_SENSORS_10MS_AMOUNT; i++) {
		if (strcmp(analogSensors10ms[i].name, changeStruct->name) == 0) {
			// Found the right sensor
			changeAnalogSensorAlarmValues(changeStruct, &analogSensors10ms[i]);
			return;
		}
	}
	for (i = 0; i < ANALOG_SENSORS_100MS_AMOUNT; i++) {
		if (strcmp(analogSensors100ms[i].name, changeStruct->name) == 0) {
			// Found the right sensor
			changeAnalogSensorAlarmValues(changeStruct, &analogSensors100ms[i]);
			return;
		}
	}
}

/**
 * Change an analog sensor's alarm values using an AnalogAlarmChangeStruct
 */
void changeBinarySensorAlarmValues(struct BinaryAlarmChangeStruct *changeStruct, struct BinarySensor *sensor) {
	strcpy(sensor->alarmName, changeStruct->alarmName);
	printf("Changed binary sensor %s", sensor->name);
}

void findAndChangeBinaryAlarm(struct BinaryAlarmChangeStruct* changeStruct) {
	int i;
	for (i = 0; i < BINARY_SENSORS_AMOUNT; i++) {
		if (strcmp(binarySensors[i].name, changeStruct->name) == 0) {
			// Found the right sensor
			changeBinarySensorAlarmValues(changeStruct, &binarySensors[i]);
			return;
		}
	}
}

